package io.lckgroup.modules.mongodb.controller;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import io.lckgroup.common.exception.BackException;
import io.lckgroup.common.utils.R;
import io.lckgroup.modules.lck.annotation.AppLogin;
import io.lckgroup.modules.mongodb.config.MongoConfig;
import io.lckgroup.modules.oss.service.SysOssService;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsCriteria;
import org.springframework.data.mongodb.gridfs.GridFsOperations;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import java.util.Optional;
import java.util.UUID;

@RestController
@RequestMapping("mongo/file")
public class FileMongoController {

    @Autowired
    private MongoConfig mongoConfig;

    @Autowired
    private GridFsTemplate gridFsTemplate;

    @Autowired
    private GridFsOperations gridFsOperations;

    @Autowired
    private SysOssService sysOssService;

    @Value("${backend.mongo.prefix}")
    private String prefix;

    /**
     * 上传文件
     */
    @PostMapping("/upload")
    @AppLogin
    public R upload(@RequestParam("file") MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            throw new BackException("上传文件不能为空");
        }
        if(!file.getContentType().startsWith("image")){
            return R.error("只能上传图片文件");
        }
        //上传文件
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        //调用MongoDB存储
        DBObject metaData = new BasicDBObject();
        metaData.put("c_time",System.currentTimeMillis());
        String fileName = UUID.randomUUID().toString() + suffix;
        InputStream inputStream  = new ByteArrayInputStream(file.getBytes());
        try {
            gridFsTemplate.store(inputStream, fileName, suffix, metaData);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BackException("上传文件失败，请重试");
        }
        String url = prefix + fileName;
        return R.ok().put("url", url);
    }

    /**
     * 获取文件
     * @param name 文件名
     * @return
     */
    @RequestMapping(path = "/{name:.+}", method = RequestMethod.GET)
    public HttpEntity<byte[]> get(@PathVariable("name") String name) {
        try {
            Optional<GridFSFile> optionalCreated = maybeLoadFile(name);
            if (optionalCreated.isPresent()) {
                GridFSFile created = optionalCreated.get();
                GridFSDownloadStream gridFSDownloadStream = mongoConfig.getGridFSBuckets().openDownloadStream(created.getObjectId());
                GridFsResource gridFsResource = new GridFsResource(created, gridFSDownloadStream);

                ByteArrayOutputStream os = new ByteArrayOutputStream();
                IOUtils.copy(gridFsResource.getInputStream(), os);
                HttpHeaders headers = new HttpHeaders();
                headers.add(HttpHeaders.CONTENT_TYPE, URLConnection.guessContentTypeFromName(name));
                return new HttpEntity<>(os.toByteArray(), headers);
            } else {
                return new ResponseEntity<>(HttpStatus.NOT_FOUND);
            }
        } catch (IOException e) {
            return new ResponseEntity<>(HttpStatus.IM_USED);
        }
    }

    /**
     * 删除文件
     * @param url 文件路径
     * @return
     */
    @RequestMapping("delete")
    @AppLogin
    public R delete(@RequestParam("url") String url) {
        String fileName = url.substring(prefix.length());
        Optional<GridFSFile> optionalCreated = maybeLoadFile(fileName);
        if (optionalCreated.isPresent()) {
            gridFsTemplate.delete(getFilenameQuery(fileName));
            sysOssService.removeByUrl(url);
        } else {
            return R.error("删除失败");
        }
        return R.ok("删除成功");
    }

    private Optional<GridFSFile> maybeLoadFile(String name) {
        GridFSFile file = gridFsOperations.findOne(getFilenameQuery(name));
        return Optional.ofNullable(file);
    }

    private static Query getFilenameQuery(String name) {
        return Query.query(GridFsCriteria.whereFilename().is(name));
    }

}
